import {
  CanActivate,
  ExecutionContext,
  Injectable,
  UnauthorizedException,
} from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { Reflector } from '@nestjs/core';
import { Request } from 'express';
import { AUTH_OPTIONS_KEY, AuthOptions } from '../decorator/auth.decorator';

@Injectable()
export class JwtAuthGuard implements CanActivate {
  constructor(
    private jwtService: JwtService,
    private reflector: Reflector,
  ) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // 从上下文获取装饰器传递的参数
    const options = this.reflector.get<AuthOptions>(
      AUTH_OPTIONS_KEY,
      context.getHandler(),
    ) || { required: true }; // 默认选项
    console.log('---auth options---', options);
    // 如果设置为不需要验证，则直接通过
    if (!options.required) {
      return true;
    }

    const request = context.switchToHttp().getRequest<Request>();
    const token = this.extractTokenFromHeader(request);

    if (!token) {
      throw new UnauthorizedException('缺少认证token');
    }

    try {
      const payload = await this.jwtService.verifyAsync(token);
      // 将用户信息挂载到request对象上，后续控制器可以直接使用
      request['userinfo'] = payload;

      // 如果有特定角色验证要求，检查用户是否有相应角色
      if (options.roles && options.roles.length > 0) {
        const userRoles = payload.roles || [];
        const hasRequiredRole = options.roles.some((role) =>
          userRoles.includes(role),
        );

        if (!hasRequiredRole) {
          throw new UnauthorizedException('权限不足，需要特定角色');
        }
      }
    } catch (error) {
      if (error.message === '权限不足，需要特定角色') {
        throw error;
      }
      throw new UnauthorizedException('无效的token');
    }

    return true;
  }

  private extractTokenFromHeader(request: Request): string | undefined {
    const [type, token] = request.headers.authorization?.split(' ') ?? [];
    return type === 'Bearer' ? token : (request.headers.token as string);
  }
}
